/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logic;

import logic.pago.Pago;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;


/**
 *
 * @author Dani
 */
public class Venta implements VentaInterface{    
    private static final String noField = "null";
    
    private Pago pago;
    private ArrayList<Prenda> prendas = new ArrayList<>();
    private Cliente comprador;
    private Empleado vendedor;
    private Calendar fecha = Calendar.getInstance();
    private String comentarios;
    private ArrayList<Vale> valesUsados = new ArrayList<>();
    private int id;
    
    /**
     * Crea la venta con los datos especificados
     * @param prendas
     * @param comprador
     * @param vendedor
     * @param fecha
     * @param comentarios
     * @param valesUsados
     * @param pago 
     */
    public Venta(List<Prenda> prendas, Cliente comprador, Empleado vendedor, Calendar fecha, String comentarios, List<Vale> valesUsados, Pago pago) {
        if (prendas == null || prendas.isEmpty() || comprador == null || vendedor == null || fecha == null || pago == null)
            throw new IllegalArgumentException("Venta no fue configurada adecuadamente");
        
        
        this.prendas.addAll(prendas);
        this.comprador = comprador;
        this.vendedor = vendedor;  
        this.fecha = fecha;
        this.comentarios = (comentarios == null) ? Venta.noField : comentarios;
        if (valesUsados != null) //queremos que no sea null, aunque puede ser vacío
            this.valesUsados.addAll(valesUsados);
        this.pago = pago;
        this.pago.setGasto(this.getPrecio()-this.getDescuento());
    }
    /**
     * Crea una venta a partir únicamente de Strings
     * Buscará todos los datos correspondientes a ello
     * en la base de datos
     * @param prendas
     * @param comprador
     * @param vendedor
     * @param fecha
     * @param comentarios
     * @param valesUsados
     * @param pago
     * @param id 
     */
    public Venta(String prendas, String comprador, String vendedor, Calendar fecha, String comentarios, String valesUsados, String pago, int id) {
        if (prendas == null || prendas.isEmpty() || comprador == null || vendedor == null || fecha == null || pago == null)
            throw new IllegalArgumentException("Venta no fue configurada adecuadamente");
        
        
        this.prendas.addAll(Prenda.parsePrendas(prendas));
        this.comprador = Cliente.buscaCliente(comprador);
        this.vendedor = Empleado.buscaEmpleado(vendedor);
        this.fecha = fecha;
        this.comentarios = (comentarios == null) ? Venta.noField : comentarios;
        if (valesUsados != null) //queremos que no sea null, aunque puede ser vacío
            this.valesUsados.addAll(Vale.parseVales(valesUsados));
        this.pago = Pago.parsePago(pago);
        this.pago.setGasto(this.getPrecio()-this.getDescuento());
        this.id = id;
    }
    /**
     * Carga una venta parseando los datos con "data"
     * Viene en este formato:
     * @param data PAGO_TARJETA;30;23123123#Vestido_de_Noche;20;Vestido_de_Verano;30#Pedrito#Juenito#31;12;2012#noCom#0010;2,40;0020;5,80;0030;6,81#12354
     */
    public Venta(String data) throws IllegalArgumentException{
        if (data == null || data.isEmpty())
            throw new IllegalArgumentException("No hay datos para crear la venta");
        String[] splitData = data.split("#");
        if (splitData.length != 8)
            throw new IllegalArgumentException("No hay el número adecuado de datos para crear la venta");
        String[] prendas = splitData[1].split(";");
        if (prendas.length %2 != 0)
            throw new IllegalArgumentException("Faltan precios o prendas");
        String[] fechas = splitData[4].split(";");
        if (fechas.length != 3)
            throw new IllegalArgumentException("Formato de fecha no válido");
        String[] vales = splitData[6].split(";");
        if (vales.length %2 != 0 && vales.length != 1 || vales.length == 1 && !vales[0].contains(noField))
            throw new IllegalArgumentException("Faltan vales o descuentos de los mismos");
        String infopago = splitData[0];
        
        this.pago = Pago.parsePagoCompleto(infopago);

        for (int i = 0; i < prendas.length; i+=2)
            this.prendas.add(new Prenda(prendas[i], Integer.parseInt(prendas[i+1])));
        
        this.comprador = new Cliente(splitData[2]);
        this.vendedor = new Empleado(splitData[3]);
        this.fecha.set(Integer.parseInt(fechas[2]),Integer.parseInt(fechas[1]),Integer.parseInt(fechas[0])); // Year/Month/Date
        this.comentarios = splitData[5];
        this.id = Integer.parseInt(splitData[7]);
        if (vales.length > 1)
            for (int i = 0; i < vales.length; i+=2)
                this.valesUsados.add(new Vale(Integer.parseInt(vales[i]), Integer.parseInt(vales[i+1])));
    }
    /**
     * Efectúa la venta en sí, actualizando las base de datos
     * de clientes, etc...
     * @return 
     */
    public boolean realizaVenta() {
        if (!this.pago.efectuar())
            return false; 
        //actualizar bases de datos
        return true;
    }
    
    /**
     * Añade un vale de descuento a la venta
     * @param vale
     * @return true si el vale tiene efecto sobre la compra, false si ya es gratis todo
     */
    public boolean addVale(Vale vale) {
        if (this.getDescuento() >= this.getPrecio())
            return false;
        this.valesUsados.add(vale);
        return true;
    }
    /**
     * Añade una nueva prenda a la venta
     * @param prenda 
     */
    public void  addPrenda (Prenda prenda){
        this.prendas.add(prenda);
    }
    /**
     * Devuelve una lista conlas prendas que tiene esta venta
     * @return 
     */
    public List<Prenda> getPrendas() {
        return this.prendas;
    }    
    /**
     * Devuelve la cantidad pagada de la venta tras aplicar descuentos
     * @return 
     */
    public int getCantidadPagada() {
        return this.pago.getGasto();
    }
    
    @Override
    public int getPrecio() {
        int coste = 0;
        for (Prenda p: prendas)
            coste += p.getPrecio();
        return coste;
    }
    @Override
    public int getDescuento() {
        int rebaja = 0;
        for (Vale v: valesUsados)
            rebaja += v.getDescuento();
        return rebaja;
    }
    @Override
    public Date getFecha() {
        return this.fecha.getTime();
    }
    @Override
    public String getCliente() {
        return this.comprador.getNombre();
    }
    @Override
    public String getEmpleado() {
        return this.vendedor.getNombre();
    }
    @Override
    public int getId() {
        return this.id;
    }
    @Override
    public String getComentarios() {
        return (this.comentarios == null ? Venta.noField == null : this.comentarios.equals(Venta.noField)) ? Venta.noField : this.comentarios;
    }
    
    @Override
    //PAGO_TARJETA#Vestido_de_Noche;20;Vestido_de_Verano;30#Pedrito#Juenito#31;12;2012#noCom#0010;2,40;0020;5,80;0030;6,81#12345
    public String toString() {
        String ret  = "";
        ret += this.pago.toString() + "#";
        for (Prenda p: this.prendas)
            ret += p.getNombre() + ";" + p.getPrecio() + ";";
        if (ret.charAt(ret.length()-1) == ';')
            ret = ret.substring(0, ret.length()-1);
        ret += "#" + this.comprador.getNombre() + "#" + this.vendedor.getNombre() + "#";
        ret += this.fecha.get(Calendar.DAY_OF_MONTH) + ";" + this.fecha.get(Calendar.MONTH) + ";" + this.fecha.get(Calendar.YEAR) + "#";
        ret += (this.comentarios == null ? Venta.noField == null : this.comentarios.equals(Venta.noField)) ? Venta.noField : this.comentarios;
        ret += "#";
        if (this.valesUsados.size() > 0) {
            for (Vale v: this.valesUsados)
                ret += v.getIdentificador() + ";" + v.getDescuento() + ";";
            if (ret.charAt(ret.length()-1) == ';')
                ret = ret.substring(0, ret.length()-1);
        } else
            ret+= noField;
        ret += "#" + this.id;

        return ret;
    }

    /**
     * Aplica una reducción de pago a la venta y genera un vale con el exceso
     * @param descuento
     * @return 
     */
    public Vale descontar(int descuento) {
        if (this.getCantidadPagada() == 0)
            return null;
        if (this.getCantidadPagada() < descuento)
            descuento = this.getCantidadPagada();
        this.pago.devuelve(descuento);
        Vale v = new Vale(new Random().nextInt(9000)+1000, descuento);
        this.valesUsados.add(v);
        return v;
    }
    
    /**
     * 
     * @param s
     * @return 0 si s coincide exactamente con el nombre de una prenda <br>
     *         >0 si s forma parcialmente una prenda <br>
     *         <0 si s no está contenido en ninguna prenda
     */
    public int buscarPrenda(String s) {
        s = s.toLowerCase();
        for (Prenda v: this.getPrendas())
            if (v.getNombre().equalsIgnoreCase(s))
                return 0;
            else if (v.getNombre().toLowerCase().contains(s))
                return 1;
        return -1;
    }
    /**
     * Devuelve true si la venta está en un intervalo de 24
     * horas desde "d", falso en cualquier otro caso
     * @param d
     * @return 
     */
    public boolean in24HourInterval(Date d) {
        return Math.abs(this.fecha.getTime().getTime() - d.getTime()) < 86400;
    }
    /**
     * Genera la factura correspondiente a esta venta
     * @return 
     */
    public Factura generarFactura() {
        return new Factura(this.comprador,this.pago, this.prendas);
    }
}
